#include "Application.h"
#include <glad/glad.h>
#include <GLFW/glfw3.h>

Application* Application::m_instance_ = nullptr;

Application* Application::getInstance()
{
    static Application instance;
    return &instance;
}

Application::Application(/* args */)
{
}

Application::~Application()
{
}

uint32_t Application::getWidth() const
{
    return m_width_;
}

uint32_t Application::getHeight() const
{
    return m_height_;
}

bool Application::init(const int& width, const int& height)
{
    m_height_ = height;
    m_width_ = width;
    //初始化glfw
    glfwInit();
    //opengl版本号
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    //使用核心模式（非立即渲染模式）
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    //创建窗口
    m_window_ = glfwCreateWindow(m_width_, m_height_, "LearnOpenGL", NULL, NULL);
    if(m_window_ == NULL){
        return false;
    }
    glfwMakeContextCurrent(m_window_);  ///设置当前窗体为opengl绘制的舞台
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return false;
    }
    
    glfwSetFramebufferSizeCallback(m_window_, frameBufferSizeCallbak);

    //键盘响应
    glfwSetKeyCallback(m_window_, keyCallback);
    
    return true;
}

bool Application::update()
{
    if(glfwWindowShouldClose(m_window_)){
        return false;
    }
    
    //事件
    //函数会交换颜色缓冲（它是一个储存着GLFW窗口每一个像素颜色值的大缓冲），它在这一迭代中被用来绘制，并且将会作为输出显示在屏幕上。
    glfwSwapBuffers(m_window_);
    glfwPollEvents();   //接收并分发窗体时间
    return true;
}

void Application::destory()
{
    glfwTerminate();  //退出程序
}

void Application::frameBufferSizeCallbak(GLFWwindow* window, int width, int height)
{
    if(Application::getInstance()->mResizeCallback != nullptr)
        Application::getInstance()->mResizeCallback(width, height);
}

void Application::keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    if (Application::getInstance()->mKeyBoardCallback != nullptr)
        Application::getInstance()->mKeyBoardCallback(key, action, mods);
}